import socket,random,json,time
"""获取本机IP"""
def get_ip_address():
    # 获取主机名称
    hostname = socket.gethostname()
    # 根据主机名称获取与之关联的IP地址
    ip_address = socket.gethostbyname(hostname)
    return ip_address
def get_network_segment(ip_address):
    # 通过分割字符串来提取IP地址的前两部分
    segments = ip_address.split('.')
    if len(segments) >= 2:
        return segments[0], segments[1]
    else:
        raise ValueError("Invalid IP address format")
# 跨机
def broadcast_find_host(data, stop_event):  # 这个data包括设备信息和用户did
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    ip_address = get_ip_address()
    part1, part2 = get_network_segment(ip_address)

    broadcast_interval = 5 + random.random()*5
    check_interval = 0.5

    while not stop_event.is_set():
        try:
            print("[跨机] 发送广播查找本机...")
            msg = f"FIND_HOST:{json.dumps(data)}".encode()
            #print(f"msg:{msg}")
            udp.sendto(msg, (f'{part1}.{part2}.255.255', 8800))
        except Exception as e:
            print(f"[跨机] 广播发送错误: {e}")
        elapsed = 0
        while elapsed < broadcast_interval and not stop_event.is_set():
            time.sleep(check_interval)
            elapsed += check_interval
    udp.close()
    print("[跨机] 广播线程已停止")

#跨机
def listen_for_host_response():
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp.bind(('', 8801))
    udp.settimeout(10)  # 缩短超时，便于重试
    retry_count = 0   #监听次数
    max_retries = 3   #最大监听次数
    try:
        while retry_count < max_retries:
            try:
                msg, addr = udp.recvfrom(1024)
                #print(f"[跨机] 收到响应: {msg.decode()}，来自 {addr}")
                response_data = json.loads(msg.decode())
                benji_did = response_data.get("benji_user_did")
                if benji_did:
                    return {'benji_did': benji_did, 'host_addr': addr[0]}
                else:
                    print("响应缺少 benji_user_did 字段")
                    return None
            except json.JSONDecodeError:
                print("[跨机] JSON解析失败，重试...")
                retry_count += 1
            except socket.timeout:
                retry_count += 1
                print(f"[跨机] 接收超时，重试 {retry_count}/{max_retries}")
        return None
    finally:
        udp.close()


def host_udp_listener1():
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 绑定所有网络接口的8800端口（正确）
    try:
        udp.bind(('', 8800))
    except OSError as e:
        print(f"[本机] 绑定8800端口失败：{e}（可能被占用）")
        udp.close()
        return None
    udp.settimeout(30)
    print("[本机] 正在监听跨机广播请求...")
    retry_count = 0
    max_retries = 3
    try:
        while retry_count < max_retries:
            try:
                msg, addr = udp.recvfrom(1024)
                print(f"[本机] 收到来自 {addr}跨机请求")
                # 检查消息前缀格式（增强健壮性）
                if not msg.startswith(b"FIND_HOST:"):
                    print("[本机] 消息格式错误，不是FIND_HOST前缀")
                    continue
                # 拆分JSON部分，处理可能的IndexError
                try:
                    json_str = msg.decode().split(":", 1)[1]
                except IndexError:
                    print("[本机] 消息格式错误，缺少JSON部分")
                    continue
                # 解析JSON，已处理JSONDecodeError
                try:
                    data = json.loads(json_str)
                except json.JSONDecodeError:
                    print("[本机] JSON解析失败，等待下一条消息...")
                    continue

                # 验证必要字段是否存在
                required_fields = ["user_did", "kuaji_user_did", "kuaji_device_information"]
                if not all(field in data for field in required_fields):
                    print(f"[本机] 跨机请求缺少必要字段：{required_fields}")
                    continue
                user_did = data["user_did"]
                kuaji_user_did = data["kuaji_user_did"]
                kuaji_device_information = data["kuaji_device_information"]
                # 验证本机DID有效性
                benji_user_did = 1
                if not benji_user_did or not isinstance(benji_user_did, str):
                    print(f"[本机] 获取本机DID失败（值为：{benji_user_did}）")
                    continue  # 不回复，继续监听
                # 比较DID是否匹配
                if user_did == benji_user_did:
                    #print(f"[本机] 跨机DID与本机一致（{user_did}）")
                    # 构造响应数据
                    response_data = {
                        "benji_user_did": benji_user_did
                    }
                    response_msg = json.dumps(response_data).encode()
                    cross_ip = addr[0]  # 跨机的IP
                    cross_port = 8801  # 跨机监听响应的端口
                    # 发送响应
                    try:
                        udp.sendto(response_msg, (cross_ip, cross_port))
                        print(f"[本机] 已回应跨机 {cross_ip}")
                        # 若只需处理一个请求，返回结果；若需持续监听，注释此行
                        return {
                            'benji_user_did': benji_user_did,
                            'kuaji_user_did': kuaji_user_did,
                            'kuaji_device_information': kuaji_device_information,
                            'kuaji_ip': cross_ip
                        }
                    except Exception as e:
                        print(f"[本机] 发送响应失败：{e}")
                else:
                    print(f"[本机] 跨机DID（{user_did}）与本机DID（{benji_user_did}）不匹配，不回复")
            except socket.timeout:
                retry_count += 1
                print(f"[本机] 监听超时，重试 {retry_count}/{max_retries}")
                if retry_count >= max_retries:
                    print("[本机] 达到最大重试次数，停止监听")
                    break
            except Exception as e:
                print(f"[本机] 处理消息时出错: {e}")
                # 发生非致命错误时继续监听（而非break）
                continue
    finally:
        udp.close()
        print("[本机] UDP监听已关闭")
    return None
import threading
import time

# 引入你已有的函数（假设它们已放在同一文件中）

# 模拟本机的监听函数
def run_host_listener():
    result = host_udp_listener1()
    print("[测试] 本机返回结果：", result)

# 模拟跨机的广播和接收响应函数
def run_cross_device():
    from threading import Event

    # 示例跨机数据
    test_data = {
        "user_did": "1",  # 必须与 host_udp_listener1 中 benji_user_did 一致才能被响应
        "kuaji_user_did": "did:p2p_did_chat:abc123",
        "kuaji_device_information": {
            "device_name": "TestDevice",
            "os": "Linux"
        }
    }

    # 创建一个停止事件控制广播线程
    stop_event = Event()
    # 启动广播线程
    broadcast_thread = threading.Thread(target=broadcast_find_host, args=(test_data, stop_event))
    broadcast_thread.start()

    # 等待响应
    response = listen_for_host_response()
    print("[测试] 跨机收到响应：", response)

    # 停止广播
    stop_event.set()
    broadcast_thread.join()

if __name__ == "__main__":
    # 启动本机监听线程
    host_thread = threading.Thread(target=run_host_listener)
    host_thread.start()

    # 稍微等待一下确保本机监听器已启动
    time.sleep(1)

    # 启动跨机模拟
    run_cross_device()

    # 等待本机线程结束
    host_thread.join()

    print("[测试] 所有线程已完成")








